package cn.asiontang.launcher;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import cn.asiontang.db.BaseEntity;
import cn.asiontang.db.BaseEntityDao;
import cn.asiontang.db.DBHelper;
import cn.asiontang.exception.LogEx;
import cn.asiontang.utils.TextUtils;
import eu.chainfire.libsuperuser.Shell;

@SuppressWarnings("unused")
public class AppInfo extends BaseEntity
{
    private static ArrayList<String> mCacheDirPaths;
    public Boolean isAllowDisableApp;
    private boolean isStopped = false;

    public static void clearCacheDir(Context context, String packageName)
    {
        for (String cacheDirPath : getCacheDirPaths(context))
            Shell.SU.run(String.format(cacheDirPath, packageName));
    }

    /**
     */
    private static ArrayList<String> getCacheDirPaths(Context context)
    {
        if (mCacheDirPaths == null)
        {
            ArrayList<String> cacheFilePaths = new ArrayList<>();
            cacheFilePaths.add(context.getCacheDir().toString());

            File externalCacheDir = context.getExternalCacheDir();
            if (externalCacheDir != null)
                cacheFilePaths.add(externalCacheDir.toString());

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
            {
                File[] externalCacheDirs = context.getExternalCacheDirs();
                for (File cacheDir : externalCacheDirs)
                    if (!cacheFilePaths.contains(cacheDir.toString()))
                        cacheFilePaths.add(cacheDir.toString());
            }

            String packageName = context.getPackageName();
            for (int i = 0; i < cacheFilePaths.size(); i++)
            {
                String cachePath = cacheFilePaths.get(i);

                // data/data/cn.asiontang.launcher/cache => /data/data/%s/cache
                cachePath = cachePath.replace(packageName, "%s");

                // rm -rf /data/data/%s/cache/*
                cachePath = String.format("rm -r %s", cachePath);

                cacheFilePaths.set(i, cachePath);
            }
            mCacheDirPaths = cacheFilePaths;
        }
        return mCacheDirPaths;
    }

    public Bitmap getAppIcon()
    {
        byte[] b = this.getValues().getAsByteArray("AppIcon");
        return BitmapFactory.decodeByteArray(b, 0, b.length, null);
    }

    public void setAppIcon(Bitmap value)
    {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try
        {
            value.compress(Bitmap.CompressFormat.PNG, 100, os);
            this.getValues().put("AppIcon", os.toByteArray());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                os.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    public String getAppName()
    {
        return this.getValue("AppName");
    }

    public void setAppName(CharSequence value)
    {
        this.setValue("AppName", TextUtils.valueOfNoNull(value));
    }

    public String getID()
    {
        return this.getValue("ID");
    }

    public void setID(String value)
    {
        this.setValue("ID", value);
    }

    public Intent getLaunchIntent()
    {
        try
        {
            String uri = getLaunchIntentRawData();
            if (uri == null || uri.length() == 0)
                return null;
            return Intent.parseUri(uri, 0);
        }
        catch (URISyntaxException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    public void setLaunchIntent(Intent intent)
    {
        if (intent != null)
            this.setValue("LaunchIntent", intent.toUri(0));
    }

    public String getLaunchIntentRawData()
    {
        return this.getValue("LaunchIntent");
    }

    public String getPackageName()
    {
        return this.getValue("PackageName");
    }

    public void setPackageName(String value)
    {
        this.setValue("PackageName", value);
    }

    public int getVersionCode()
    {
        return this.getValues().getAsInteger("VersionCode");
    }

    public void setVersionCode(int value)
    {
        this.getValues().put("VersionCode", value);
    }

    public String getVersionName()
    {
        return this.getValue("VersionName");
    }

    public void setVersionName(String value)
    {
        this.setValue("VersionName", value);
    }

    public Boolean isEnabled()
    {
        return "1".equals(this.getValueNoNull("Enabled"));
    }

    public Boolean isHide()
    {
        return "1".equals(this.getValueNoNull("Hide"));
    }

    public boolean isStopped()
    {
        return isStopped;
    }

    public Boolean isSystem()
    {
        return "1".equals(this.getValueNoNull("System"));
    }

    public void setFlags(int flags)
    {
        setIsSystem(flags);

        setIsStopped(flags);
    }

    public void setIsEnabled(boolean value)
    {
        this.setValue("Enabled", value ? "1" : "0");
    }

    public void setIsHide(boolean value)
    {
        this.setValue("Hide", value ? "1" : "0");
    }

    public void setIsStopped(int flags)
    {
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB_MR1)
            return;
        setIsStopped((flags & ApplicationInfo.FLAG_STOPPED) != 0);
    }

    public void setIsStopped(boolean stopped)
    {
        isStopped = stopped;
    }

    public void setIsSystem(int flags)
    {
        boolean value = (flags & ApplicationInfo.FLAG_SYSTEM) != 0 || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
        this.setValue("System", value ? "1" : "0");
    }

    public static class DAO extends BaseEntityDao<AppInfo>
    {
        public DAO(Context context)
        {
            super(context);
        }

        public List<String> getAllAppPackageNameList()
        {
            return DBHelper.getStringList(DBHelper.getCursor(R.string.sql_get_all_package_name));
        }

        public List<AppInfo> getAllList()
        {
            Cursor cursor = DBHelper.getCursorByArgs(R.string.sql_get_all_apps);
            final List<AppInfo> list = new ArrayList<>();
            try
            {
                final int count = cursor.getCount();
                if (count == 0)
                    return list;

                final String[] columnNames = cursor.getColumnNames();
                ContentValues item;
                while (cursor.moveToNext())
                {
                    item = new ContentValues();
                    for (int i = 0; i < columnNames.length; i++)
                        if ("AppIcon".equals(columnNames[i]))
                            item.put(columnNames[i], cursor.getBlob(i));
                        else
                            item.put(columnNames[i], cursor.getString(i));

                    final AppInfo t = new AppInfo();
                    t.setValues(item);
                    list.add(t);
                }
                return list;
            }
            catch (final Exception e)
            {
                LogEx.e("AppInfo.DAO.getList", e);
            }
            finally
            {
                DBHelper.closeSilently(cursor);
            }
            return list;
        }

        /**
         * 获取APP列表
         *
         * @param showHideOrNot 是否只获取被隐藏的APP列表
         */
        public List<AppInfo> getList(boolean showHideOrNot)
        {
            Cursor cursor = DBHelper.getCursorByArgs(R.string.sql_get_apps_by_is_hide, showHideOrNot ? "1" : "0");
            final List<AppInfo> list = new ArrayList<>();
            try
            {
                final int count = cursor.getCount();
                if (count == 0)
                    return list;

                final String[] columnNames = cursor.getColumnNames();
                ContentValues item;
                while (cursor.moveToNext())
                {
                    item = new ContentValues();
                    for (int i = 0; i < columnNames.length; i++)
                        if ("AppIcon".equals(columnNames[i]))
                            item.put(columnNames[i], cursor.getBlob(i));
                        else
                            item.put(columnNames[i], cursor.getString(i));

                    final AppInfo t = new AppInfo();
                    t.setValues(item);
                    list.add(t);
                }
                return list;
            }
            catch (final Exception e)
            {
                LogEx.e("AppInfo.DAO.getList", e);
            }
            finally
            {
                DBHelper.closeSilently(cursor);
            }
            return list;
        }

        public void save(AppInfo item)
        {
            super.save("AppInfos", item);
        }

        public void saveAll(List<AppInfo> list)
        {
            DBHelper.execSQL(R.string.sql_clear_all_apps);
            this.save("AppInfos", list);
        }
    }
}